home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / bash-1.12 / dist / variables.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-18  |  38.1 KB  |  1,609 lines

  1. /* variables.c -- Functions for hacking shell variables. */
  2.  
  3. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  4.  
  5.    This file is part of GNU Bash, the Bourne Again SHell.
  6.  
  7.    Bash is free software; you can redistribute it and/or modify it
  8.    under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 1, or (at your option)
  10.    any later version.
  11.  
  12.    Bash is distributed in the hope that it will be useful, but WITHOUT
  13.    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  14.    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
  15.    License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with Bash; see the file COPYING.  If not, write to the Free
  19.    Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <pwd.h>
  24. #include <sys/types.h>
  25.  
  26. #include "shell.h"
  27. #include "hash.h"
  28. #include "flags.h"
  29.  
  30. #if defined (USG) && !defined (isc386) && !defined (sgi)
  31. struct passwd *getpwuid (), *getpwent ();
  32. #endif
  33.  
  34. /* The list of shell variables that the user has created, or that came from
  35.    the environment. */
  36. HASH_TABLE *shell_variables = (HASH_TABLE *)NULL;
  37.  
  38. /* The list of shell functions that the user has created, or that came from
  39.    the environment. */
  40. HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
  41.  
  42. /* The current variable context.  This is really a count of how deep into
  43.    executing functions we are. */
  44. int variable_context = 0;
  45.  
  46. /* The array of shell assignments which are made only in the environment
  47.    for a single command. */
  48. char **temporary_env = (char **)NULL;
  49.  
  50. /* Some funky variables which are known about specially.  Here is where
  51.    "$*", "$1", and all the cruft is kept. */
  52. char *dollar_vars[10];
  53. WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
  54.  
  55. /* The value of $$. */
  56. int dollar_dollar_pid;
  57.  
  58. /* An array which is passed to commands as their environment.  It is
  59.    manufactured from the overlap of the initial environment and the
  60.    shell variables that are marked for export. */
  61. char **export_env = (char **)NULL;
  62.  
  63. /* Non-zero means that we have to remake EXPORT_ENV. */
  64. int array_needs_making = 1;
  65.  
  66. /* The list of variables that may not be unset in this shell. */
  67. char **non_unsettable_vars = (char **)NULL;
  68.  
  69. #if defined (USG)
  70. #define DEFAULT_MAIL_PATH "/usr/mail/"
  71. #else
  72. #define DEFAULT_MAIL_PATH "/usr/spool/mail/"
  73. #endif
  74.  
  75. /* Some forward declarations. */
  76. SHELL_VAR *set_if_not ();    /* returns new or existing entry */
  77. static void sbrand ();        /* set bash random number generator */
  78.  
  79. /* Make VAR be auto-exported.  VAR is a pointer to a SHELL_VAR. */
  80. #define set_auto_export(var) \
  81. { var->attributes |= att_exported; array_needs_making = 1; }
  82.  
  83. /* Initialize the shell variables from the current environment. */
  84. initialize_shell_variables (env)
  85.      char *env[];
  86. {
  87.   extern char *primary_prompt, *secondary_prompt;
  88.   char *name, *string;
  89.   int c, char_index;
  90.   int string_index = 0;
  91.   SHELL_VAR *temp_var;
  92.  
  93.   if (!shell_variables)
  94.     shell_variables = make_hash_table (0);
  95.  
  96.   if (!shell_functions)
  97.     shell_functions = make_hash_table (0);
  98.  
  99.   /* Set up $PWD. */
  100.   {
  101.     char *get_working_directory (), *cd;
  102.  
  103.     cd = get_working_directory ("shell-init");
  104.     if (cd)
  105.       {
  106.     bind_variable ("PWD", cd);
  107.     free (cd);
  108.       }
  109.   }
  110.  
  111.   while (string = env[string_index++])
  112.     {
  113.       char_index = 0;
  114.  
  115.       name = (char *)alloca (1 + strlen (string));
  116.  
  117.       while ((c = *string++) && c != '=')
  118.     name[char_index++] = c;
  119.  
  120.       name[char_index] = '\0';
  121.  
  122.       /* If exported function, define it now. */
  123.       /* Posix.2 style exported function: name()=value */
  124.       if (strncmp ("() {", string, 4) == 0 ||
  125.       ((name[char_index - 1] == ')' &&
  126.         name[char_index - 2] == '(' &&
  127.         string[0] == '{')))
  128.     {
  129.       char *eval_string;
  130.  
  131.       eval_string = (char *)xmalloc (3 + strlen (string) + strlen (name));
  132.       sprintf (eval_string, "%s %s", name, string);
  133.       parse_and_execute (eval_string, name);
  134.  
  135.       if (name[char_index - 1] == ')')
  136.         name[char_index - 2] = '\0';
  137.       set_func_auto_export (name);
  138.     }
  139.       else
  140.     {
  141.       SHELL_VAR *v;
  142.  
  143.       v = bind_variable (name, string);
  144.       set_auto_export (v);
  145.     }
  146.     }
  147.  
  148.   /* Remember this pid. */
  149.   dollar_dollar_pid = (int)getpid ();
  150.  
  151.   /* Now make our own defaults in case the vars that we think are
  152.      important are missing. */
  153.   temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
  154.   set_auto_export (temp_var);
  155.  
  156.   temp_var = set_if_not ("TERM", "dumb");
  157.   set_auto_export (temp_var);
  158.  
  159.   set_if_not ("PS1", primary_prompt);
  160.   set_if_not ("PS2", secondary_prompt);
  161.   set_if_not ("IFS", " \t\n");
  162.  
  163.   /* Magic machine types.  Pretty convenient. */
  164.   temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
  165.   set_auto_export (temp_var);
  166.  
  167.   /* Default MAILPATH, and MAILCHECK. */
  168.   set_if_not ("MAILCHECK", "60");
  169.   if ((get_string_value ("MAIL") == (char *)NULL) &&
  170.       (get_string_value ("MAILPATH") == (char *)NULL))
  171.     {
  172.       extern char *current_user_name;
  173.       char *tem;
  174.  
  175.       tem = (char *)xmalloc (1 + sizeof (DEFAULT_MAIL_PATH)
  176.                + strlen (current_user_name));
  177.       strcpy (tem, DEFAULT_MAIL_PATH);
  178.       strcat (tem, current_user_name);
  179.  
  180.       bind_variable ("MAILPATH", tem);
  181.       free (tem);
  182.     }
  183.  
  184.   /* Do some things with shell level. */
  185.   temp_var = set_if_not ("SHLVL", "0");
  186.   set_auto_export (temp_var);
  187.   adjust_shell_level (1);
  188.  
  189.   /* Make a variable $PPID, which holds the pid of the shell's parent.  */
  190.   {
  191.     char *ppid;
  192.     SHELL_VAR *v;
  193.     extern char *itos ();
  194.  
  195.     ppid = itos ((int) getppid ());
  196.     v = find_variable ("PPID");
  197.  
  198.     if (v)
  199.       v->attributes &= ~att_readonly;
  200.  
  201.     v = bind_variable ("PPID", ppid);
  202.     v->attributes |= (att_readonly | att_integer);
  203.  
  204.     non_unsettable ("PPID");
  205.     free (ppid);
  206.   }
  207.  
  208. #if defined (GETOPTS_BUILTIN)
  209.   /* Initialize the `getopts' stuff. */
  210.   bind_variable ("OPTIND", "1");
  211.   bind_variable ("OPTERR", "1");
  212. #endif /* GETOPTS_BUILTIN */
  213.  
  214.   /* Get the full pathname to THIS shell, and set the BASH variable
  215.      to it. */
  216.   {
  217.     extern char *shell_name, *find_user_command (), *full_pathname ();
  218.     extern int login_shell;
  219.     char *tname = find_user_command (shell_name);
  220.  
  221.     if ((login_shell == 1) && (*shell_name != '/'))
  222.       {
  223.     struct passwd *entry = getpwuid (getuid ());
  224.  
  225.     if (entry)
  226.       {
  227.         /* If HOME doesn't exist, set it. */
  228.         temp_var = (SHELL_VAR *)find_variable ("HOME");
  229.         if (!temp_var)
  230.           {
  231.         temp_var = bind_variable ("HOME", entry->pw_dir);
  232.         temp_var->attributes |= att_exported;
  233.           }
  234.         name = savestring (entry->pw_shell);
  235.       }
  236.     else
  237.       name = savestring ("a.out");
  238.     endpwent ();
  239.       }
  240.     else
  241.       {
  242.     if (!tname)
  243.       {
  244.         char *make_absolute ();
  245.         name = make_absolute (shell_name, get_string_value ("PWD"));
  246.       }
  247.     else
  248.       {
  249.         name = full_pathname (tname);
  250.         free (tname);
  251.       }
  252.       }
  253.  
  254.     /* Make the exported environment variable SHELL be whatever the name of
  255.        this shell is.  Note that the `tset' command looks at this variable
  256.        to determine what style of commands to output; if it ends in "csh",
  257.        then C-shell commands are output, else Bourne shell commands. */
  258.     temp_var = set_if_not ("SHELL", name);
  259.     set_auto_export (temp_var);
  260.  
  261.     /* Make a variable called BASH, which is the name of THIS shell. */
  262.     temp_var = bind_variable ("BASH", name);
  263.     temp_var->attributes |= att_exported;
  264.  
  265.     free (name);
  266.   }
  267.  
  268.   /* Make a variable called BASH_VERSION which contains the version info. */
  269.   {
  270.     char tt[12];
  271.     extern char *dist_version;
  272.     extern int build_version;
  273.  
  274.     sprintf (tt, "%s.%d", dist_version, build_version);
  275.     bind_variable ("BASH_VERSION", tt);
  276.   }
  277.  
  278.   /* Set history variables to defaults, and then do whatever we would
  279.      do if the variable had just been set. */
  280.   {
  281.     char *tilde_expand ();
  282.     char *tem = tilde_expand ("~/.bash_history");
  283.  
  284.     set_if_not ("HISTFILE", tem);
  285.     free (tem);
  286.  
  287.     set_if_not ("HISTSIZE", "500");
  288.     sv_histsize ("HISTSIZE");
  289.   }
  290.  
  291.   /* seed the random number generator */
  292.  
  293.   sbrand (dollar_dollar_pid);
  294.  
  295.   /* If we have inherited `noclobber' from a previous shell, then set
  296.      noclobbering on. */
  297.   {
  298.     extern int noclobber;
  299.  
  300.     noclobber = find_variable ("noclobber") != NULL;
  301.   }
  302.  
  303.   /* Initialize the dynamic variables, and seed their values */
  304.   initialize_dynamic_variables ();
  305.  
  306.   non_unsettable ("PATH");
  307.   non_unsettable ("PS1");
  308.   non_unsettable ("PS2");
  309.   non_unsettable ("IFS");
  310.  
  311.   /* Get the users real user id, and save that in an readonly variable.
  312.      To make the variable *really* readonly, we have added it to a special
  313.      list of vars. */
  314.  
  315.   sv_uids ();
  316.   set_var_read_only ("UID");
  317.   set_var_read_only ("EUID");
  318.  
  319.   non_unsettable ("EUID");
  320.   non_unsettable ("UID");
  321. }
  322.  
  323. adjust_shell_level (change)
  324.      int change;
  325. {
  326.   extern int shell_level;
  327.   extern char *itos ();
  328.   char *new_level;
  329.   int old_level;
  330.  
  331.  
  332.   old_level = atoi (get_string_value ("SHLVL"));
  333.   shell_level = old_level + change;
  334.   new_level = itos (shell_level);
  335.   bind_variable ("SHLVL", new_level);
  336.   free (new_level);
  337. }
  338.  
  339. /* Add NAME to the list of variables that cannot be unset
  340.    if it isn't already there. */
  341. non_unsettable (name)
  342.      char *name;
  343. {
  344.   register int i;
  345.  
  346.   if (!non_unsettable_vars)
  347.     {
  348.       non_unsettable_vars = (char **)xmalloc (1 * sizeof (char *));
  349.       non_unsettable_vars[0] = (char *)NULL;
  350.     }
  351.  
  352.   for (i = 0; non_unsettable_vars[i]; i++)
  353.     if (strcmp (non_unsettable_vars[i], name) == 0)
  354.       return;
  355.  
  356.   non_unsettable_vars = (char **)
  357.     xrealloc (non_unsettable_vars, (2 + i) * sizeof (char *));
  358.   non_unsettable_vars[i] = savestring (name);
  359.   non_unsettable_vars[i + 1] = (char *)NULL;
  360. }
  361.  
  362. /* Set NAME to VALUE if NAME has no value. */
  363. SHELL_VAR *
  364. set_if_not (name, value)
  365.      char *name, *value;
  366. {
  367.   SHELL_VAR *v = find_variable (name);
  368.  
  369.   if (!v)
  370.     v = bind_variable (name, value);
  371.   return (v);
  372. }
  373.  
  374. /* Map FUNCTION over the variables in VARIABLES.  Return an array of the
  375.    variables that satisfy FUNCTION.  Satisfy means that FUNCTION returns
  376.    a non-zero value for.  A NULL value for FUNCTION means to use all
  377.    variables. */
  378. SHELL_VAR **
  379. map_over (function, var_hash_table)
  380.      Function *function;
  381.      HASH_TABLE* var_hash_table;
  382. {
  383.   register int i;
  384.   register BUCKET_CONTENTS *tlist;
  385.   SHELL_VAR *var, **list = (SHELL_VAR **)NULL;
  386.   int list_index = 0, list_size = 0;
  387.  
  388.   for (i = 0; i < var_hash_table->nbuckets; i++)
  389.     {
  390.       tlist = get_hash_bucket (i, var_hash_table);
  391.  
  392.       while (tlist)
  393.     {
  394.       var = (SHELL_VAR *)tlist->data;
  395.  
  396.       if (!function || (*function) (var))
  397.         {
  398.           if (list_index + 1 >= list_size)
  399.         list = (SHELL_VAR **)
  400.           xrealloc (list, (list_size += 20) * sizeof (SHELL_VAR *));
  401.  
  402.           list[list_index++] = var;
  403.           list[list_index] = (SHELL_VAR *)NULL;
  404.         }
  405.       tlist = tlist->next;
  406.     }
  407.     }
  408.   return (list);
  409. }
  410.  
  411. int
  412. qsort_var_comp (var1, var2)
  413.      SHELL_VAR **var1, **var2;
  414. {
  415.   return (strcmp ((*var1)->name, (*var2)->name));
  416. }
  417.  
  418. sort_variables (array)
  419.      SHELL_VAR **array;
  420. {
  421.   qsort (array, array_len (array), sizeof (SHELL_VAR *), qsort_var_comp);
  422. }
  423.  
  424. /* Create a NULL terminated array of all the shell variables in TABLE. */
  425. static SHELL_VAR **
  426. all_vars (table)
  427.      HASH_TABLE *table;
  428. {
  429.   SHELL_VAR **list;
  430.  
  431.   list = map_over ((Function *)NULL, table);
  432.   if (list)
  433.     sort_variables (list);
  434.   return (list);
  435. }
  436.  
  437. /* Create a NULL terminated array of all the shell variables. */
  438. SHELL_VAR **
  439. all_shell_variables ()
  440. {
  441.   return (all_vars (shell_variables));
  442. }
  443.  
  444. /* Create a NULL terminated array of all the shell functions. */
  445. SHELL_VAR **
  446. all_shell_functions ()
  447. {
  448.   return (all_vars (shell_functions));
  449. }
  450.  
  451. /* Print VARS to stdout in such a way that they can be read back in. */
  452. print_var_list (list)
  453.      register SHELL_VAR **list;
  454. {
  455.   register int i;
  456.   register SHELL_VAR *var;
  457.  
  458.   for (i = 0; list && (var = list[i]); i++)
  459.     if (!invisible_p (var))
  460.       print_assignment (var);
  461. }
  462.  
  463. #if defined (NOTDEF)
  464. /* Print LIST (a linked list of shell variables) to stdout
  465.    by printing the names, without the values.  Used to support the
  466.    `set +' command. */
  467. print_vars_no_values (list)
  468.      register SHELL_VAR **list;
  469. {
  470.   register int i;
  471.   register SHELL_VAR *var;
  472.  
  473.   for (i = 0; list && (var = list[i]); i++)
  474.     if (!invisible_p (var))
  475.       printf ("%s\n", var->name);
  476. }
  477. #endif
  478.  
  479. /* Print the value of a single SHELL_VAR.  No newline is
  480.    output, but the variable is printed in such a way that
  481.    it can be read back in. */
  482. print_assignment (var)
  483.      SHELL_VAR *var;
  484. {
  485.   if (function_p (var) && var->value)
  486.     {
  487.       printf ("%s=", var->name);
  488.       print_var_function (var);
  489.       printf ("\n");
  490.     }
  491.   else if (var->value)
  492.     {
  493.       printf ("%s=", var->name);
  494.       print_var_value (var);
  495.       printf ("\n");
  496.     }
  497. }
  498.  
  499. /* Print the value cell of VAR, a shell variable.  Do not print
  500.    the name, nor leading/trailing newline. */
  501. print_var_value (var)
  502.      SHELL_VAR *var;
  503. {
  504.   if (var->value)
  505.     printf ("%s", var->value);
  506. }
  507.  
  508. /* Print the function cell of VAR, a shell variable.  Do not
  509.    print the name, nor leading/trailing newline. */
  510. print_var_function (var)
  511.      SHELL_VAR *var;
  512. {
  513.   char *named_function_string ();
  514.  
  515.   if (function_p (var) && var->value)
  516.     printf ("%s", named_function_string ((char *)NULL, var->value, 1));
  517. }
  518.  
  519.  
  520. /* **************************************************************** */
  521. /*                                                                  */
  522. /*                 Dynamic Variable Extension                       */
  523. /*                                                                  */
  524. /* **************************************************************** */
  525.  
  526. /* DYNAMIC VARIABLES
  527.    
  528.    These are variables whose values are generated anew each time they are
  529.    referenced.  These are implemented using a pair of function pointers
  530.    in the struct variable: assign_func, which is called from bind_variable,
  531.    and dynamic_value, which is called from find_variable.
  532.    
  533.    assign_func is called from bind_variable, if bind_variable discovers
  534.    that the variable being assigned to has such a function.  The function
  535.    is called as
  536.       SHELL_VAR *temp = (*(entry->assign_func)) (entry, value)
  537.    and the (SHELL_VAR *)temp is returned as the value of bind_variable.  It
  538.    is usually ENTRY (self).
  539.    
  540.    dynamic_value is called from find_variable to return a `new' value for
  541.    the specified dynamic varible.  If this function is NULL, the variable
  542.    is treated as a `normal' shell variable.  If it is not, however, then
  543.    this function is called like this:
  544.       tempvar = (*(var->dynamic_value)) (var);
  545.    
  546.    Sometimes `tempvar' will replace the value of `var'.  Other times, the
  547.    shell will simply use the string value.  Pretty object-oriented, huh?
  548.    
  549.    Be warned, though: if you `unset' a special variable, it loses its
  550.    special meaning, even if you subsequently set it.
  551.    
  552.    The special assignment code would probably have been better put in
  553.    subst.c: do_assignment, in the same style as
  554.    stupidly_hack_special_variables, but I wanted the changes as
  555.    localized as possible.  */
  556.  
  557. /* The value of $SECONDS.  This is the number of seconds since shell
  558.    invocation, or, the number of seconds since the last assignment + the
  559.    value of the last assignment. */
  560. static long seconds_value_assigned = (long)0;
  561.  
  562. /* Originally defined in shell.c */
  563. extern time_t shell_start_time;
  564.  
  565. SHELL_VAR *
  566. assign_seconds (self, value)
  567.      SHELL_VAR *self;
  568.      char *value;
  569. {
  570.   seconds_value_assigned = atol (value);
  571.   shell_start_time = NOW;
  572.   return (self);
  573. }
  574.  
  575. SHELL_VAR *
  576. get_seconds (var)
  577.      SHELL_VAR *var;
  578. {
  579.   extern char *itos ();
  580.   time_t time_since_start;
  581.   char *p;
  582.  
  583.   time_since_start = NOW - shell_start_time;
  584.   p = itos((int) seconds_value_assigned + time_since_start);
  585.  
  586.   if (var->value)
  587.     free (var->value);
  588.  
  589.   var->attributes |= att_integer;
  590.   var->value = p;
  591.   return (var);
  592. }
  593.  
  594. /* The random number seed.  You can change this by setting RANDOM. */
  595. static unsigned long rseed = 1;
  596.  
  597. /* A linear congruential random number generator based on the ANSI
  598.    C standard.  A more complicated one is overkill.  */
  599.  
  600. /* Returns a pseudo-random number between 0 and 32767. */
  601. static int
  602. brand ()
  603. {
  604.   rseed = rseed * 1103515245 + 12345;
  605.   return ((unsigned int)(rseed / 65536) % 32768);
  606. }
  607.  
  608. /* Set the random number generator seed to SEED. */
  609. static void
  610. sbrand (seed)
  611.      int seed;
  612. {
  613.   rseed = seed;
  614. }
  615.  
  616. static SHELL_VAR *
  617. assign_random (self, value)
  618.      SHELL_VAR *self;
  619.      char *value;
  620. {
  621.   int s = atoi (value);
  622.  
  623.   sbrand (s);
  624.   return (self);
  625. }
  626.  
  627. static SHELL_VAR *
  628. get_random (var)
  629.      SHELL_VAR *var;
  630. {
  631.   int rv;
  632.   char *p;
  633.   extern char *itos ();
  634.  
  635.   rv = brand ();
  636.   p = itos ((int)rv);
  637.   if (var->value)
  638.     free (var->value);
  639.  
  640.   var->attributes |= att_integer;
  641.   var->value = p;
  642.   return (var);
  643. }
  644.  
  645. /* Function which returns the current line number. */
  646. static SHELL_VAR *
  647. get_lineno (var)
  648.      SHELL_VAR *var;
  649. {
  650.   extern int line_number;
  651.   char *p;
  652.   extern char *itos ();
  653.  
  654.   p = itos (line_number);
  655.   if (var->value)
  656.     free (var->value);
  657.   var->value = p;
  658.   return (var);
  659. }
  660.  
  661. initialize_dynamic_variables ()
  662. {
  663.   SHELL_VAR *v;
  664.  
  665.   v = bind_variable ("SECONDS", (char *)NULL);
  666.   v->dynamic_value = get_seconds;
  667.   v->assign_func = assign_seconds;
  668.  
  669.   v = bind_variable ("RANDOM", (char *)NULL);
  670.   v->dynamic_value = get_random;
  671.   v->assign_func = assign_random;
  672.  
  673.   v = bind_variable ("LINENO", (char *)NULL);
  674.   v->dynamic_value = get_lineno;
  675.   v->assign_func = (DYNAMIC_FUNC *)NULL;
  676. }
  677.  
  678. /* How to get a pointer to the shell variable or function named NAME.
  679.    HASHED_VARS is a pointer to the hash table containing the list
  680.    of interest (either variables or functions). */
  681. SHELL_VAR *
  682. var_lookup (name, hashed_vars)
  683.      char *name;
  684.      HASH_TABLE *hashed_vars;
  685. {
  686.   BUCKET_CONTENTS *bucket;
  687.  
  688.   bucket = find_hash_item (name, hashed_vars);
  689.  
  690.   if (bucket)
  691.     return ((SHELL_VAR *)bucket->data);
  692.   else
  693.     return ((SHELL_VAR *)NULL);
  694. }
  695.  
  696. /* Look up the variable entry whose name matches STRING.
  697.    Returns the entry or NULL. */
  698. SHELL_VAR *
  699. find_variable (name)
  700.      char *name;
  701. {
  702.   extern int variable_context;
  703.   extern Function *this_shell_builtin;
  704.   SHELL_VAR *find_tempenv_variable ();
  705.   SHELL_VAR *var = (SHELL_VAR *)NULL;
  706.  
  707.   /* If we are executing a function or builtin, first look in the
  708.      temporary environment for the variable.  This allows constructs
  709.      such as "foo=x eval 'echo $foo'" to get the `exported' value
  710.      of $foo. */
  711.   if (variable_context || this_shell_builtin)
  712.     var = find_tempenv_variable (name);
  713.  
  714.   if (!var)
  715.     var = var_lookup (name, shell_variables);
  716.  
  717.   if (!var)
  718.     return ((SHELL_VAR *)NULL);
  719.  
  720.   if (var->dynamic_value)
  721.     return ((*(var->dynamic_value)) (var));
  722.   else
  723.     return (var);
  724. }
  725.  
  726. /* Look up the function entry whose name matches STRING.
  727.    Returns the entry or NULL. */
  728. SHELL_VAR *
  729. find_function (name)
  730.      char *name;
  731. {
  732.   return (var_lookup (name, shell_functions));
  733. }
  734.  
  735. /* Return the string value of a variable.  Return NULL if the variable
  736.    doesn't exist, or only has a function as a value.  Don't cons a new
  737.    string. */
  738. char *
  739. get_string_value (var_name)
  740.      char *var_name;
  741. {
  742.   SHELL_VAR *var = find_variable (var_name);
  743.  
  744.   if (!var)
  745.     return (char *)NULL;
  746.   else
  747.     return (var->value);
  748. }
  749.  
  750. /* Create a local variable referenced by NAME. */
  751. SHELL_VAR *
  752. make_local_variable (name)
  753.      char *name;
  754. {
  755.   SHELL_VAR *new_var, *old_var, *bind_variable ();
  756.   BUCKET_CONTENTS *elt;
  757.  
  758.   /* local foo; local foo;  is a no-op. */
  759.   old_var = find_variable (name);
  760.   if (old_var && old_var->context == variable_context)
  761.     return (old_var);
  762.  
  763.   elt = remove_hash_item (name, shell_variables);
  764.   if (elt)
  765.     {
  766.       old_var = (SHELL_VAR *)elt->data;
  767.       free (elt->key);
  768.       free (elt);
  769.     }
  770.   else
  771.     old_var = (SHELL_VAR *)NULL;
  772.  
  773.   /* If a variable does not already exist with this name, then
  774.      just make a new one. */
  775.   if (!old_var)
  776.     {
  777.       new_var = bind_variable (name, "");
  778.     }
  779.   else
  780.     {
  781.       new_var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  782.  
  783.       new_var->name = savestring (name);
  784.       new_var->value = savestring ("");
  785.  
  786.       new_var->dynamic_value = (DYNAMIC_FUNC *)NULL;
  787.       new_var->assign_func = (DYNAMIC_FUNC *)NULL;
  788.  
  789.       new_var->attributes = 0;
  790.  
  791.       if (exported_p (old_var))
  792.     new_var->attributes |= att_exported;
  793.  
  794.       new_var->prev_context = old_var;
  795.       elt = add_hash_item (savestring (name), shell_variables);
  796.       elt->data = (char *)new_var;
  797.     }
  798.  
  799.   new_var->context = variable_context;
  800.   return (new_var);
  801. }
  802.  
  803. /* Bind a variable NAME to VALUE.  This conses up the name
  804.    and value strings. */
  805. SHELL_VAR *
  806. bind_variable (name, value)
  807.      char *name, *value;
  808. {
  809.   SHELL_VAR *entry = var_lookup (name, shell_variables);
  810.  
  811.   if (!entry)
  812.     {
  813.       /* Make a new entry for this variable.  Then do the binding. */
  814.       entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  815.  
  816.       entry->attributes = 0;
  817.       entry->name = savestring (name);
  818.  
  819.       if (value)
  820.     entry->value = savestring (value);
  821.       else
  822.     entry->value = (char *)NULL;
  823.  
  824.       entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
  825.       entry->assign_func = (DYNAMIC_FUNC *)NULL;
  826.  
  827.       /* Always assume variables are to be made at toplevel!
  828.      make_local_variable has the responsibilty of changing the
  829.      variable context. */
  830.       entry->context = 0;
  831.       entry->prev_context = (SHELL_VAR *)NULL;
  832.  
  833.       {
  834.     BUCKET_CONTENTS *elt;
  835.  
  836.     elt = add_hash_item (savestring (name), shell_variables);
  837.     elt->data = (char *)entry;
  838.       }
  839.     }
  840.   else if (entry->assign_func)
  841.     return ((*(entry->assign_func)) (entry, value));
  842.   else
  843.     {
  844.       if (readonly_p (entry))
  845.     {
  846.       report_error ("%s: read-only variable", name);
  847.       return (entry);
  848.     }
  849.  
  850.       /* If this variable has had its type set to integer (via `declare -i'),
  851.      then do expression evaluation on it and store the result.  The
  852.      functions in expr.c (evalexp and bind_int_variable) are responsible
  853.      for turning off the integer flag if they don't want further
  854.      evaluation done. */
  855.       if (integer_p (entry))
  856.     {
  857.       long val, evalexp();
  858.       extern char *itos();
  859.  
  860.       val = evalexp (value);
  861.       /* We cannot free () entry->value before this; what if the string
  862.          we are working is `even=even+2'?  We need the original value
  863.          around while we are doing the evaluation to handle any possible
  864.          recursion. */
  865.       if (entry->value)
  866.         free (entry->value);
  867.  
  868.       entry->value = itos (val);
  869.     }
  870.       else
  871.     {
  872.       if (entry->value)
  873.         free (entry->value);
  874.  
  875.       if (value)
  876.         entry->value = savestring (value);
  877.       else
  878.         entry->value = (char *)NULL;
  879.     }
  880.     }
  881.  
  882.   if (mark_modified_vars)
  883.     entry->attributes |= att_exported;
  884.  
  885.   if (exported_p (entry))
  886.     array_needs_making = 1;
  887.  
  888.   return (entry);
  889. }
  890.  
  891. /* Dispose of the information attached to VAR. */
  892. dispose_variable (var)
  893.      SHELL_VAR *var;
  894. {
  895.   if (!var)
  896.     return;
  897.  
  898.   if (function_p (var))
  899.     dispose_command (var->value);
  900.   else if (var->value)
  901.     free (var->value);
  902.  
  903.   free (var->name);
  904.  
  905.   if (exported_p (var))
  906.     array_needs_making = 1;
  907.  
  908.   free (var);
  909. }
  910.  
  911. /* Unset the variable referenced by NAME. */
  912. unbind_variable (name)
  913.      char *name;
  914. {
  915.   SHELL_VAR *var = find_variable (name);
  916.  
  917.   if (!var)
  918.     return (-1);
  919.  
  920.   if (var->value)
  921.     {
  922.       free (var->value);
  923.       var->value = (char *)NULL;
  924.     }
  925.  
  926.   makunbound (name, shell_variables);
  927.  
  928.   return (0);
  929. }
  930.  
  931. /* Make the variable associated with NAME go away.  HASH_LIST is the
  932.    hash table from which this variable should be deleted (either
  933.    shell_variables or shell_functions).
  934.    Returns non-zero if the variable couldn't be found. */
  935. makunbound (name, hash_list)
  936.      char *name;
  937.      HASH_TABLE *hash_list;
  938. {
  939.   BUCKET_CONTENTS *elt;
  940.   SHELL_VAR *old_var, *new_var;
  941.  
  942.   elt = remove_hash_item (name, hash_list);
  943.  
  944.   if (!elt)
  945.     return (-1);
  946.  
  947.   old_var = (SHELL_VAR *)elt->data;
  948.   new_var = old_var->prev_context;
  949.  
  950.   if (old_var && exported_p (old_var))
  951.     array_needs_making++;
  952.  
  953.   if (new_var)
  954.     {
  955.       /* Has to be a variable, functions don't have previous contexts. */
  956.       BUCKET_CONTENTS *new_elt;
  957.  
  958.       new_elt = add_hash_item (savestring (new_var->name), hash_list);
  959.       new_elt->data = (char *)new_var;
  960.  
  961.       if (exported_p (new_var))
  962.     set_var_auto_export (new_var->name);
  963.     }
  964.  
  965.   free (elt->key);
  966.   free (elt);
  967.  
  968.   dispose_variable (old_var);
  969.   stupidly_hack_special_variables (name);
  970.   return (0);
  971. }
  972.  
  973. /* Remove the variable with NAME if it is a local variable in the
  974.    current context. */
  975. kill_local_variable (name)
  976.      char *name;
  977. {
  978.   SHELL_VAR *temp = find_variable (name);
  979.  
  980.   if (temp && (temp->context == variable_context))
  981.     {
  982.       makunbound (name, shell_variables);
  983.       return (0);
  984.     }
  985.   return (-1);
  986. }
  987.  
  988. /* Get rid of all of the variables in the current context. */
  989. int
  990. variable_in_context (var)
  991.      SHELL_VAR *var;
  992. {
  993.   return (var && var->context == variable_context);
  994. }
  995.  
  996. kill_all_local_variables ()
  997. {
  998.   register int i, pass;
  999.   register SHELL_VAR *var, **list;
  1000.   HASH_TABLE *varlist;
  1001.  
  1002.   for (pass = 0; pass < 2; pass++)
  1003.     {
  1004.       varlist = pass ? shell_functions : shell_variables;
  1005.  
  1006.       list = map_over (variable_in_context, varlist);
  1007.  
  1008.       if (list)
  1009.     {
  1010.       for (i = 0; var = list[i]; i++)
  1011.         makunbound (var->name, varlist);
  1012.  
  1013.       free (list);
  1014.     }
  1015.     }
  1016. }
  1017.  
  1018. /* Delete the entire contents of the hash table. */
  1019. delete_all_variables (hashed_vars)
  1020.      HASH_TABLE *hashed_vars;
  1021. {
  1022.   register int i;
  1023.   register BUCKET_CONTENTS *bucket;
  1024.  
  1025.   for (i = 0; i < hashed_vars->nbuckets; i++)
  1026.     {
  1027.       bucket = hashed_vars->bucket_array[i];
  1028.  
  1029.       while (bucket)
  1030.     {
  1031.       BUCKET_CONTENTS *temp = bucket;
  1032.       SHELL_VAR *var, *prev;
  1033.  
  1034.       bucket = bucket->next;
  1035.  
  1036.       var = (SHELL_VAR *)temp->data;
  1037.  
  1038.       while (var)
  1039.         {
  1040.           prev = var->prev_context;
  1041.           dispose_variable (var);
  1042.  
  1043.           var = prev;
  1044.         }
  1045.  
  1046.       free (temp->key);
  1047.       free (temp);
  1048.     }
  1049.       hashed_vars->bucket_array[i] = (BUCKET_CONTENTS *)NULL;
  1050.     }
  1051. }
  1052.  
  1053. SHELL_VAR *
  1054. new_shell_variable (name)
  1055.      char *name;
  1056. {
  1057.   SHELL_VAR *var;
  1058.  
  1059.   var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  1060.  
  1061.   bzero (var, sizeof (SHELL_VAR));
  1062.   var->name = savestring (name);
  1063.   return (var);
  1064. }
  1065.  
  1066. /* Do a function binding to a variable.  You pass the name and
  1067.    the command to bind to.  This conses the name and command. */
  1068. SHELL_VAR *
  1069. bind_function (name, value)
  1070.      char *name;
  1071.      COMMAND *value;
  1072. {
  1073.   SHELL_VAR *entry = find_function (name);
  1074.  
  1075.   if (!entry)
  1076.     {
  1077.       BUCKET_CONTENTS *elt;
  1078.  
  1079.       elt = add_hash_item (savestring (name), shell_functions);
  1080.  
  1081.       elt->data = (char *)new_shell_variable (name);
  1082.       entry = (SHELL_VAR *)elt->data;
  1083.       entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
  1084.       entry->assign_func = (DYNAMIC_FUNC *)NULL;
  1085.  
  1086.       /* Functions are always made at the top level.  This allows a
  1087.      function to define another function (like autoload). */
  1088.       entry->context = 0;
  1089.     }
  1090.  
  1091.   if (entry->value)
  1092.     dispose_command (entry->value);
  1093.  
  1094.   if (value)    /* I don't think this can happen anymore */
  1095.     entry->value = (char *)copy_command (value);
  1096.   else
  1097.     entry->value = (char *)NULL;
  1098.  
  1099.   entry->attributes |= att_function;
  1100.  
  1101.   if (mark_modified_vars)
  1102.     entry->attributes |= att_exported;
  1103.  
  1104.   entry->attributes &= ~att_invisible;    /* Just to be sure */
  1105.  
  1106.   array_needs_making = 1;
  1107.  
  1108.   return (entry);
  1109. }
  1110.  
  1111. /* Copy VAR to a new data structure and return that structure. */
  1112. SHELL_VAR *
  1113. copy_variable (var)
  1114.      SHELL_VAR *var;
  1115. {
  1116.   SHELL_VAR *copy = (SHELL_VAR *)NULL;
  1117.  
  1118.   if (var)
  1119.     {
  1120.       copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  1121.  
  1122.       copy->attributes = var->attributes;
  1123.       copy->name = savestring (var->name);
  1124.  
  1125.       if (function_p (var))
  1126.     copy->value = (char *)copy_command (var->value);
  1127.       else if (var->value)
  1128.     copy->value = savestring (var->value);
  1129.       else
  1130.     copy->value = (char *)NULL;
  1131.  
  1132.       copy->dynamic_value = var->dynamic_value;
  1133.       copy->assign_func = var->assign_func;
  1134.  
  1135.       copy->context = var->context;
  1136.  
  1137.       /* Don't bother copying previous contexts along with this variable. */
  1138.       copy->prev_context = (SHELL_VAR *)NULL;
  1139.     }
  1140.   return (copy);
  1141. }
  1142.  
  1143. /* Make the variable associated with NAME be read-only.
  1144.    If NAME does not exist yet, create it. */
  1145. set_var_read_only (name)
  1146.      char *name;
  1147. {
  1148.   SHELL_VAR *entry = find_variable (name);
  1149.  
  1150.   if (!entry)
  1151.     {
  1152.       entry = bind_variable (name, "");
  1153.       if (!no_invisible_vars)
  1154.     entry->attributes |= att_invisible;
  1155.     }
  1156.   entry->attributes |= att_readonly;
  1157. }
  1158.  
  1159. /* Make the function associated with NAME be read-only.
  1160.    If NAME does not exist, we just punt, like auto_export code below. */
  1161. set_func_read_only (name)
  1162.      char *name;
  1163. {
  1164.   SHELL_VAR *entry = find_function (name);
  1165.  
  1166.   if (entry)
  1167.     entry->attributes |= att_readonly;
  1168. }
  1169.  
  1170. /* Make the variable associated with NAME be auto-exported.
  1171.    If NAME does not exist yet, create it. */
  1172. set_var_auto_export (name)
  1173.      char *name;
  1174. {
  1175.   SHELL_VAR *entry = find_variable (name);
  1176.  
  1177.   if (!entry)
  1178.     {
  1179.       entry = bind_variable (name, "");
  1180.       if (!no_invisible_vars)
  1181.     entry->attributes |= att_invisible;
  1182.     }
  1183.  
  1184.   set_auto_export (entry);
  1185. }
  1186.  
  1187. /* Make the function associated with NAME be auto-exported. */
  1188. set_func_auto_export (name)
  1189.      char *name;
  1190. {
  1191.   SHELL_VAR *entry = find_function (name);
  1192.  
  1193.   if (entry)
  1194.     {
  1195.       entry->attributes |= att_exported;
  1196.       array_needs_making = 1;
  1197.     }
  1198. }
  1199.  
  1200. /* Returns non-zero if STRING is an assignment statement.  The returned value
  1201.    is the index of the `=' sign. */
  1202. assignment (string)
  1203.      char *string;
  1204. {
  1205.   register int c, index = 0;
  1206.  
  1207.   c = string[index];
  1208.  
  1209.   if (!isletter (c) && c != '_')
  1210.     return (0);
  1211.  
  1212.   while (c = string[index])
  1213.     {
  1214.       /* The following is safe.  Note that '=' at the start of a word
  1215.      is not an assignment statement. */
  1216.       if (c == '=')
  1217.     return (index);
  1218.  
  1219.       if (!isletter (c) && !digit (c) && c != '_')
  1220.     return (0);
  1221.  
  1222.       index++;
  1223.     }
  1224.   return (0);
  1225. }
  1226.  
  1227. int
  1228. visible_var (var)
  1229.      SHELL_VAR *var;
  1230. {
  1231.   return (!invisible_p (var));
  1232. }
  1233.  
  1234. SHELL_VAR **
  1235. all_visible_variables ()
  1236. {
  1237.   SHELL_VAR **list;
  1238.  
  1239.   list = map_over (visible_var, shell_variables);
  1240.  
  1241.   if (list)
  1242.     sort_variables (list);
  1243.  
  1244.   return (list);
  1245. }
  1246.  
  1247. SHELL_VAR **
  1248. all_visible_functions ()
  1249. {
  1250.   SHELL_VAR **list;
  1251.  
  1252.   list = map_over (visible_var, shell_functions);
  1253.  
  1254.   if (list)
  1255.     sort_variables (list);
  1256.  
  1257.   return (list);
  1258. }
  1259.  
  1260. /* Return non-zero if the variable VAR is visible and exported. */
  1261. int
  1262. visible_and_exported (var)
  1263.      SHELL_VAR *var;
  1264. {
  1265.   return (!invisible_p (var) && exported_p (var));
  1266. }
  1267.  
  1268. /* Make an array of assignment statements from the hash table
  1269.    HASHED_VARS which contains SHELL_VARs.  Only visible, exported
  1270.    variables are eligible. */
  1271. char **
  1272. make_var_array (hashed_vars)
  1273.      HASH_TABLE *hashed_vars;
  1274. {
  1275.   register int i, list_index;
  1276.   register SHELL_VAR *var;
  1277.   char **list = (char **)NULL;
  1278.   SHELL_VAR **vars;
  1279.  
  1280.   vars = map_over (visible_and_exported, hashed_vars);
  1281.  
  1282.   if (!vars)
  1283.     return (char **)NULL;
  1284.  
  1285.   list = (char **)xmalloc ((1 + array_len ((char **)vars)) * sizeof (char *));
  1286.  
  1287.   for (i = 0, list_index = 0; var = vars[i]; i++)
  1288.     {
  1289.       char *value, *named_function_string ();
  1290.  
  1291.       if (function_p (var))
  1292.     {
  1293.       value =
  1294.         named_function_string ((char *)NULL,
  1295.                    (COMMAND *)function_cell (var), 0);
  1296.     }
  1297.       else
  1298.     value = value_cell (var);
  1299.  
  1300.       if (value)
  1301.     {
  1302. #if 0
  1303.       list[list_index] =
  1304.         (char *)xmalloc (2 + strlen (var->name) + strlen (value));
  1305.  
  1306.       sprintf (list[list_index], "%s=%s", var->name, value);
  1307. #else
  1308.       /* Let's see if this makes any kind of performance difference. */
  1309.       int name_len = strlen (var->name);
  1310.       int value_len = strlen (value);
  1311.       char    *p;
  1312.  
  1313.       p = list[list_index] =  (char *)xmalloc (2 + name_len + value_len);
  1314.       strcpy (p, var->name);
  1315.       p[name_len] = '=';
  1316.       strcpy (&p[name_len + 1], value);
  1317. #endif
  1318.       list_index++;
  1319.     }
  1320.     }
  1321.  
  1322.   free (vars);
  1323.   list[list_index] = (char *)NULL;
  1324.   return (list);
  1325. }
  1326.  
  1327. /* Add STRING to the array of foo=bar strings that we already
  1328.    have to add to the environment.  */
  1329. assign_in_env (string)
  1330.      char *string;
  1331. {
  1332.   int size;
  1333.  
  1334.   int offset = assignment (string);
  1335.   char *name = savestring (string);
  1336.   char *temp, *value = (char *)NULL;
  1337.  
  1338.   if (name[offset] == '=')
  1339.     {
  1340.       char *tilde_expand (), *string_list ();
  1341.       WORD_LIST *list, *expand_string_unsplit ();
  1342.  
  1343.       name[offset] = 0;
  1344.       temp = name + offset + 1;
  1345.       temp = tilde_expand (temp);
  1346.  
  1347.       list = expand_string_unsplit (temp, 0);
  1348.       value = string_list (list);
  1349.  
  1350.       if (list)
  1351.     dispose_words (list);
  1352.  
  1353.       free (temp);
  1354.     }
  1355.  
  1356.   if (!value) value = savestring ("");
  1357.  
  1358.   temp = (char *)xmalloc (2 + strlen (name) + strlen (value));
  1359.   sprintf (temp, "%s=%s", name, value);
  1360.   free (name);
  1361.  
  1362.   if (!temporary_env)
  1363.     {
  1364.       temporary_env = (char **)xmalloc (sizeof (char *));
  1365.       temporary_env [0] = (char *)NULL;
  1366.     }
  1367.  
  1368.   size = array_len (temporary_env);
  1369.   temporary_env = (char **)
  1370.     xrealloc (temporary_env, (size + 2) * (sizeof (char *)));
  1371.  
  1372.   temporary_env[size] = (temp);
  1373.   temporary_env[size + 1] = (char *)NULL;
  1374.   array_needs_making = 1;
  1375.  
  1376.   if (echo_command_at_execute)
  1377.     {
  1378.       /* The K*rn shell prints the `+ ' in front of assignment statements,
  1379.      so we do too. */
  1380.       extern char *indirection_level_string ();
  1381.       fprintf (stderr, "%s%s\n", indirection_level_string (), temp);
  1382.       fflush (stderr);
  1383.     }
  1384. }
  1385.  
  1386. /* Find a variable in the temporary environment that is named NAME.
  1387.    Return a consed variable, or NULL if not found. */
  1388. SHELL_VAR *
  1389. find_tempenv_variable (name)
  1390.      char *name;
  1391. {
  1392.   register int i, l = strlen (name);
  1393.  
  1394.   if (!temporary_env)
  1395.     return ((SHELL_VAR *)NULL);
  1396.  
  1397.   for (i = 0; temporary_env[i]; i++)
  1398.     {
  1399.       if (strncmp (temporary_env[i], name, l) == 0 &&
  1400.       temporary_env[i][l] == '=')
  1401.     {
  1402.       SHELL_VAR *temp;
  1403.  
  1404.       temp = new_shell_variable (name);
  1405.  
  1406.       if (temporary_env[i][l + 1])
  1407.         temp->value = savestring (&temporary_env[i][l + 1]);
  1408.       else
  1409.         temp->value = savestring ("");
  1410.       temp->attributes = att_exported;
  1411.       temp->context = 0;
  1412.       temp->prev_context = (SHELL_VAR *)NULL;
  1413.  
  1414.       temp->dynamic_value = (DYNAMIC_FUNC *)NULL;
  1415.       temp->assign_func = (DYNAMIC_FUNC *)NULL;
  1416.  
  1417.       return (temp);
  1418.     }
  1419.     }
  1420.   return ((SHELL_VAR *)NULL);
  1421. }
  1422.  
  1423. /* Free the storage used in the variable array for temporary
  1424.    environment variables. */
  1425. dispose_used_env_vars ()
  1426. {
  1427.   if (!temporary_env)
  1428.     return;
  1429.  
  1430.   free_array (temporary_env);
  1431.   temporary_env = (char **)NULL;
  1432.   array_needs_making = 1;
  1433. }
  1434.  
  1435. /* Stupid comparison routine for qsort () ing strings. */
  1436. int
  1437. qsort_string_compare (s1, s2)
  1438.      register char **s1, **s2;
  1439. {
  1440.   return (strcmp (*s1, *s2));
  1441. }
  1442.  
  1443. /* Sort ARRAY, a null terminated array of pointers to strings. */
  1444. sort_char_array (array)
  1445.      char **array;
  1446. {
  1447.   qsort (array, array_len (array), sizeof (char *), qsort_string_compare);
  1448. }
  1449.  
  1450. #define ISFUNC(s, o) ((s[o + 1] == '(')  && (s[o + 2] == ')'))
  1451.  
  1452. /* Add ASSIGN to ARRAY, or supercede a previous assignment in the
  1453.    array with the same left-hand side.  Return the new array. */
  1454. char **
  1455. add_or_supercede (assign, array)
  1456.      char *assign;
  1457.      register char **array;
  1458. {
  1459.   register int i;
  1460.   int equal_offset = assignment (assign);
  1461.  
  1462.   if (!equal_offset)
  1463.     return (array);
  1464.  
  1465.   /* If this is a function, then only supercede the function definition.
  1466.      We do this by including the `=(' in the comparison.  */
  1467.   if (assign[equal_offset + 1] == '(')
  1468.     equal_offset++;
  1469.  
  1470.   for (i = 0; array[i]; i++)
  1471.     {
  1472.       if (STREQN (assign, array[i], equal_offset + 1))
  1473.     {
  1474.       free (array[i]);
  1475.       array[i] = savestring (assign);
  1476.       return (array);
  1477.     }
  1478.     }
  1479.   array = (char **)xrealloc (array, ((2 + i) * sizeof (char *)));
  1480.   array[i++] = savestring (assign);
  1481.   array[i] = (char *)NULL;
  1482.   return (array);
  1483. }
  1484.  
  1485. /* Make the environment array for the command about to be executed.  If the
  1486.    array needs making.  Otherwise, do nothing.  If a shell action could
  1487.    change the array that commands receive for their environment, then the
  1488.    code should `array_needs_making++'. */
  1489. maybe_make_export_env ()
  1490. {
  1491.   register int i;
  1492.   register char **temp_array;
  1493.  
  1494.   if (array_needs_making)
  1495.     {
  1496.       if (export_env)
  1497.     free_array (export_env);
  1498.  
  1499. #ifdef SHADOWED_ENV
  1500.       export_env =
  1501.     (char **)xmalloc ((1 + array_len (shell_environment)) * sizeof (char *));
  1502.  
  1503.       for (i = 0; shell_environment[i]; i++)
  1504.     export_env[i] = savestring (shell_environment[i]);
  1505.       export_env[i] = (char *)NULL;
  1506.  
  1507. #else /* !SHADOWED_ENV */
  1508.  
  1509.       export_env = (char **)xmalloc (sizeof (char *));
  1510.       export_env[0] = (char *)NULL;
  1511.  
  1512. #endif /* SHADOWED_ENV */
  1513.  
  1514.       temp_array = make_var_array (shell_variables);
  1515.       for (i = 0; temp_array && temp_array[i]; i++)
  1516.     export_env = add_or_supercede (temp_array[i], export_env);
  1517.       free_array (temp_array);
  1518.  
  1519.       temp_array = make_var_array (shell_functions);
  1520.       for (i = 0; temp_array && temp_array[i]; i++)
  1521.     export_env = add_or_supercede (temp_array[i], export_env);
  1522.       free_array (temp_array);
  1523.  
  1524.       if (temporary_env)
  1525.     {
  1526.       for (i = 0; temporary_env[i]; i++)
  1527.         export_env = add_or_supercede (temporary_env[i], export_env);
  1528.  
  1529.       /* Sort the array alphabetically. */
  1530.       sort_char_array (export_env);
  1531.     }
  1532.       array_needs_making = 0;
  1533.     }
  1534. }
  1535.  
  1536. /* We always put _ in the environment as the name of this command. */
  1537. put_command_name_into_env (command_name)
  1538.      char *command_name;
  1539. {
  1540.   char *dummy;
  1541.  
  1542.   dummy = (char *)xmalloc (4 + strlen (command_name));
  1543.  
  1544.   /* These three statements replace a call to sprintf */
  1545.   dummy[0] = '_';
  1546.   dummy[1] = '=';
  1547.   strcpy (&dummy[2], command_name);
  1548.   export_env = add_or_supercede (dummy, export_env);
  1549.   free (dummy);
  1550. }
  1551.  
  1552. /* We supply our own version of getenv () because we want library
  1553.    routines to get the changed values of exported variables. */
  1554. char *last_tempenv_value = (char *)NULL;
  1555.  
  1556. /* The NeXT C library has getenv () defined and used in the same file.
  1557.    This screws our scheme.  However, Bash will run on the NeXT using
  1558.    the C library getenv (), since right now the only environment variable
  1559.    that we care about is HOME, and that is already defined.  */
  1560. #if defined (__STDC__)
  1561. #  define _CONST_HACK const
  1562. #else
  1563. #  define _CONST_HACK
  1564. #endif /* !__STDC__ */
  1565.  
  1566. #if !defined (NeXT)
  1567. char *
  1568. getenv (name)
  1569.      char _CONST_HACK *name;
  1570. {
  1571.   SHELL_VAR *var = find_tempenv_variable (name);
  1572.  
  1573.   if (var)
  1574.     {
  1575.       if (last_tempenv_value)
  1576.     free (last_tempenv_value);
  1577.  
  1578.       last_tempenv_value = savestring (value_cell (var));
  1579.       dispose_variable (var);
  1580.       return (last_tempenv_value);
  1581.     }
  1582.   else if (shell_variables)
  1583.     {
  1584.       var = find_variable (name);
  1585.       if (var && exported_p (var))
  1586.     return (value_cell (var));
  1587.     }
  1588.   else
  1589.     {
  1590.       register int i, len = strlen (name);
  1591.       extern char **environ;
  1592.  
  1593.       /* In some cases, s5r3 invokes getenv() before main(); BSD systems
  1594.          using gprof also exhibit this behavior.  This means that
  1595.          shell_variables will be 0 when this is invoked.  We look up the
  1596.      variable in the real environment in that case. */
  1597.  
  1598.       for (i = 0; environ[i]; i++)
  1599.     {
  1600.       if ((strncmp (environ[i], name, len) == 0) &&
  1601.           (environ[i][len] == '='))
  1602.         return (environ[i] + len + 1);
  1603.     }
  1604.     }
  1605.  
  1606.   return ((char *)NULL);
  1607. }
  1608. #endif /* NeXT */
  1609.